<?php

declare(strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */
namespace App\Service;

use App\Constants\Constants;

use App\Exception\CustomException;
use Hyperf\HttpMessage\Upload\UploadedFile;
use Hyperf\HttpServer\Contract\RequestInterface;

/**
 * 文件上传服务
 *
 * @author 刘兴永(aile8880@qq.com)
 * @package App\Services
 */
class UploadService extends Service
{
    /**
     * 文件上传处理
     *
     * @param UploadedFile $file
     * @return array
     */
    public function handle(UploadedFile $file)
    {
        try {
            if (!$file->isValid()) {
                throw new CustomException('UPLOAD.UPLOAD_FAIL');
            }

            // 判断文件类型
            $mime = strtolower($file->getMimeType());
            foreach (Constants::UPLOADS_CONFIG as $option) {
                if (in_array($mime, $option['mime'])) {
                    // 图片大小限制
                    if ($file->getSize() > $option['maxSize']) {
                        throw new CustomException('UPLOAD.IMAGE_SIZE_EXCEED');
                    }
                    // 目录
                    $directory = $option['directory'];
                }
            }

            if (!isset($directory)) {
                throw new CustomException('UPLOAD.FILE_FORMAT_ERROR');
            }

            // 获取文件路径
            $tmp_file = ((string)$file->getFileInfo());
            $file_name = md5_file($tmp_file) . '.' . $file->getExtension();

            // 执行文件上传
            if (($uri = $this->upload($tmp_file, $file_name, $directory)) === false) {
                throw new CustomException('UPLOAD.UPLOAD_FAIL');
            }
        }
        catch(CustomException $e) {
            return [
                'filename' => $file->getClientFilename(),
                'status' => false,
                'message' => __('COMMON.' . $e->getMessage())
            ];
        }

        // TODO 若要带上文件域名，请在 uri 前面拼接 gConfig('ali_oss_domain')
        return [
            'filename' => $file->getClientFilename(),
            'status' => true,
            'uri' => $uri ?? null
        ];
    }

    /**
     * 文件上传器
     *
     * @param string $tmp_file 临时文件地址
     * @param string $file_name 文件名
     * @param string $directory 文件目录
     * @return mixed
     */
    private function upload(string $tmp_file, string $file_name, $directory = 'file')
    {
        $file_path = $directory . '/' . date('Ymd') . '/' . $file_name;

        try {
            $content = file_get_contents($tmp_file);

            $accessKeyId = gConfig('ali_accessKeyId');
            $accessKeySecret = gConfig('ali_accessSecret');
            $endpoint = gConfig('ali_oss_endpoint');
            $bucket = gConfig('ali_oss_bucket');

            $config = new \EasySwoole\Oss\AliYun\Config([
                'accessKeyId' => $accessKeyId,
                'accessKeySecret' => $accessKeySecret,
                'endpoint' => $endpoint
            ]);
            $ossClient = new \EasySwoole\Oss\AliYun\OssClient($config);

            // 不阻塞主线程
            go(function() use ($ossClient, $bucket, $file_path, $content){
                if (!$ossClient->doesObjectExist($bucket, $file_path)) {
                    $ossClient->putObject($bucket, $file_path, $content);
                }
            });
        }
        catch (CustomException $e) {
            $request = $this->container->get(RequestInterface::class);
            // 记录日志
            $this->logger('oss')->error($e->getMessage(), [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'url' => $request->fullUrl()
            ]);
            return false;
        }

        return $file_path;
    }

    /**
     * 文件上传器
     *
     * @param string $tmp_file 临时文件地址
     * @param string $file_name 文件名
     * @param string $directory 文件目录
     * @return mixed
     */
    public function qrCodeUpload(string $tmp_file, string $file_name, $directory = 'images')
    {
        $file_path = $directory . '/' . date('Ymd') . '/' . $file_name;

        try {
            $content = file_get_contents($tmp_file);

            $accessKeyId = gConfig('ali_accessKeyId');
            $accessKeySecret = gConfig('ali_accessSecret');
            $endpoint = gConfig('ali_oss_endpoint');
            $bucket = gConfig('ali_oss_bucket');

            $config = new \EasySwoole\Oss\AliYun\Config([
                'accessKeyId' => $accessKeyId,
                'accessKeySecret' => $accessKeySecret,
                'endpoint' => $endpoint
            ]);
            $ossClient = new \EasySwoole\Oss\AliYun\OssClient($config);

            // 不阻塞主线程
            go(function() use ($ossClient, $bucket, $file_path, $content){
                if (!$ossClient->doesObjectExist($bucket, $file_path)) {
                    $ossClient->putObject($bucket, $file_path, $content);
                }
            });
        }
        catch (CustomException $e) {
            $request = $this->container->get(RequestInterface::class);
            // 记录日志
            $this->logger('oss')->error($e->getMessage(), [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'url' => $request->fullUrl()
            ]);
            return false;
        }

        return $file_path;
    }
}